Computer processor design is an extremely complex and lengthy process. The design process includes a range of tasks from high-level tasks such as specifying the architecture down to low-level tasks such as determining the physical placement of transistors on a silicon substrate. Each stage of the design process also involves extensive testing and verification of the design through that stage. One typical stage of processor design is to program the desired architecture for the processor using a register transfer language (RTL). The desired architecture is represented by an RTL specification that describes the behavior of the processor in terms of step-wise register contents. The RTL specification models what the processor does without describing the physical circuit details. Thus, the processor architecture can be verified at a high level with reference to the RTL specification, independent of implementation details such as circuit design and transistor layout. The RTL specification also facilitates later hardware design of the processor.
The testing process is complicated for architectures supporting multiple cache memories. For example, a computer architecture may support multiple processors or processor cores having either a shared memory, multiple dedicated memories, or both, as well as multiple cache memories (referred to hereinafter simply as caches). Multiple memory agents may be provided to handle memory operations or transactions in the system that access the shared memory or other memories and the caches. For example, one of the processor cores may initiate a read transaction to read a line of memory. The line of memory may be stored in one or more locations in the system, such as in the shared memory and in one or more of the caches. The memory agents work together to determine the source from which the line of memory should be read for the processor core.
The memory agents and memories may be connected in a number of ways, such as by a bus or by a point-to-point (P2P) link network using any of a number of suitable protocols. A single memory transaction may be quite complex, involving requests and data being sent back and forth among the multiple memory agents, memories, and caches. The sequence of data transmissions depends upon the type of transaction (read, write, etc.), the locations and states of the line of memory in the system, the bus protocol employed, etc. Therefore, testing the operation of the memory agents in the system can be an extremely complex and data-intensive procedure.
The testing process is further complicated by the need to identify transactions, such as those processed by the memory agents, that are initiated but which do not complete. To cite an example, a given processor or processor core may generate many transactions (e.g., read requests, write requests, etc.), each of which has certain defined finish criteria that indicate when the transaction is completed. If a given transaction does not end, there is a potential a flaw in the processor design. In addition to unending transactions, other transactions may never have an opportunity to complete. For instance, a given read or write request may be denied if there is a conflict (e.g., an address or resource conflict). If a later retry is not successful, the request may go uncompleted.
Unfortunately, the occurrence of such unending or incomplete transactions may not be identified during the verification testing. In such a case, the processor designer may be ignorant of a potential flaw in the processor design, and discovery of the flaw may be delayed until late in the design process, or even after processor fabrication has been completed.